package xin.nick.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.util.CollectionUtils;
import xin.nick.common.constant.SystemConstants;
import xin.nick.common.entity.Result;
import xin.nick.common.entity.ResultCode;
import xin.nick.common.filter.JwtAuthenticationTokenFilter;
import xin.nick.common.util.ResultUtil;

import java.util.List;

/**
 * @author Nick
 * @since 2022/7/20/020
 */
@Configuration
@EnableWebSecurity
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {


    @Autowired
    private IgnoreWhiteProperties ignoreWhiteProperties;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    /**
     * 配置过滤器
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        // 禁用 csrf
        http.csrf().disable();

        // 去掉session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 配置认证失败处理 异常返回
        http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
            ResultUtil.responseResult(response, Result.error(ResultCode.UNAUTHORIZED));
        });

        // 配置没有权限处理 异常返回
        http.exceptionHandling().accessDeniedHandler((request, response, authException) -> {
            ResultUtil.responseResult(response, Result.error(ResultCode.FORBIDDEN));
        });


        // 开放其他页面权限
        List<String> whiteList = ignoreWhiteProperties.getWhites();
        if (!CollectionUtils.isEmpty(whiteList)) {
            for (String ignoreWhite : whiteList) {
                http.authorizeRequests()
                        .antMatchers(ignoreWhite)
                        .permitAll();
            }
        }
        // 验证,登录地址放行
        http.authorizeRequests().antMatchers(SystemConstants.CODE_PATH).permitAll();
        http.authorizeRequests().antMatchers(SystemConstants.LOGIN_PATH).permitAll();

        // 配置只有未登录才可以访问的地址
//        http.authorizeRequests().antMatchers("/api/test/abab").anonymous();

        // 指定所有的OPTIONS请求直接通过
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();

        // 设置跨域
        http.cors();

        // 遍历权限表,将权限信息和拦截url配置好

        // 指定拦截需要授权才可以登录的路径
        List<String> authList = ignoreWhiteProperties.getAuths();
        if (!CollectionUtils.isEmpty(authList)) {
            for (String authPath : authList) {
                http.authorizeRequests()
                        .antMatchers(authPath)
                        .authenticated();
            }
        }

        // 角色判断,需要在被权限拦截的列表中,且登录之后才可以有效果
        http.authorizeRequests().antMatchers("/api/testRoleAdmin").hasRole("ADMIN");


        // jwt过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(jwtAuthenticationTokenFilter, LogoutFilter.class);

        return http.build();
    }



}
